package com.huawei.chengdu.meetingdemo.view;

import android.content.Context;
import android.graphics.PixelFormat;
import android.provider.Settings;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.device.idea.meeting.CallCtrl.model.CallStatus;
import com.device.idea.meeting.CallCtrl.model.ConfParam;
import com.device.idea.meeting.CallCtrl.model.ConfState;
import com.device.idea.meeting.ConfCtrl.model.ParticipantInfo;
import com.huawei.chengdu.meetingdemo.R;
import com.huawei.chengdu.meetingdemo.consts.ConfConst;
import com.huawei.chengdu.meetingdemo.consts.DialogConst;
import com.huawei.chengdu.meetingdemo.consts.ObserverConts;
import com.huawei.chengdu.meetingdemo.presenter.ConfSdkPresenter;
import com.huawei.chengdu.meetingdemo.presenter.MeetingManager;
import com.huawei.chengdu.meetingdemo.util.AppContext;
import com.huawei.chengdu.meetingdemo.util.LogUtil;
import com.huawei.chengdu.meetingdemo.view.dialogs.CustomFloatWindow;
import com.huawei.chengdu.meetingdemo.view.dialogs.DialPadDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.FloatWindowCustomBase;
import com.huawei.chengdu.meetingdemo.view.dialogs.InviteSiteDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.LeaveDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.MeetingSettingDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.ParticipantsDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.RequestFloatPermissionDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.ShareItemSelectDialog;
import com.huawei.chengdu.meetingdemo.view.dialogs.VoiceSelectWindow;

import java.util.List;
import java.util.function.Consumer;

public class MeetingControlView implements IViewDataObserver {
    private static final String TAG = MeetingControlView.class.getSimpleName();
    private View view;
    private WindowManager windowManager;
    private WindowManager.LayoutParams layoutParams;
    private LeaveDialog leaveDialog;
    private LinearLayout llBottomTitle;
    private FrameLayout llLeave;
    private FrameLayout llCamera;
    private ImageView llCameraImg;
    private FrameLayout llMute;
    private FrameLayout llParticipant;
    private TextView tvSiteCount;
    private FrameLayout llInvite;
    private FrameLayout llDialPad;
    private FrameLayout llShare;
    private ImageView llMuteImg;
    private FrameLayout llSpeaker;
    private ImageView llSpeakerImg;
    private FrameLayout llMore;
    private MeetingSettingDialog meetingSettingDialog;
    private ParticipantsDialog participantsDialog;
    private VoiceSelectWindow voiceSelectWindow;
    private Context mContext;
    public static ShareItemSelectDialog shareItemSelectDialog;
    //麦克风默认打开
    private boolean isMicOpen = true;
    private boolean isCameraOpen = true;
    //扬声器
    private boolean isQuite;
    private float maxPosX = 0f;

    private volatile boolean isViewInit = false;

    private final Consumer<ConfState> confStateListener = this::handleConfStateChangeNotify;

    // 测量尺寸的规格，0为默认值，请勿改动
    private int measureSpecWidth = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

    // 测量尺寸的规格，0为默认值，请勿改动
    private int measureSpecHeight = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    /**
     * 窗口X坐标，初始化为0
     */
    private int xInfo = 1196;

    /**
     * 窗口Y坐标，初始化为0
     */
    private int yInfo = 0;

    public MeetingControlView(Context context) {
        mContext = context;
        initView();
        initLayoutParam();
        initListener();
    }

    private void initView() {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        view = layoutInflater.inflate(R.layout.bottom_window_manager, null);
        llLeave = view.findViewById(R.id.ll_leave);
        llBottomTitle = view.findViewById(R.id.ll_bottom_title);
        llCamera = view.findViewById(R.id.ll_camera);
        llCameraImg = view.findViewById(R.id.ll_camera_img);
        llMute = view.findViewById(R.id.ll_mute);
        llMuteImg = view.findViewById(R.id.ll_mute_img);
        llParticipant = view.findViewById(R.id.ll_participant);
        tvSiteCount = view.findViewById(R.id.tv_participants_count);
        llInvite = view.findViewById(R.id.ll_invite);
        llDialPad = view.findViewById(R.id.ll_dialpad);
        llMore = view.findViewById(R.id.ll_more);
        llShare = view.findViewById(R.id.ll_share);
        llSpeakerImg = view.findViewById(R.id.ll_speaker_img);
        llSpeaker = view.findViewById(R.id.ll_speaker);
        voiceSelectWindow = new VoiceSelectWindow(mContext, llSpeaker.getLeft(), this);
        voiceSelectWindow.setAnchorView(llSpeaker);
        measureBottomWidth();
        xInfo = (int) maxPosX / 2 + ConfConst.HORIZONTAL_MARGIN_DISTANCE / 2;
        yInfo = ConfConst.BOTTOM_CONF_MIN_Y;
        isViewInit = true;
    }

    public void refreshControlItemStatus() {
        llParticipant.setVisibility(View.GONE);
        llInvite.setVisibility(View.GONE);
        muteState();
        speakerState();
        cameraState();
    }

    private void initLayoutParam() {
        windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        layoutParams = new WindowManager.LayoutParams();
        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.x = 0;
        layoutParams.y = 18;
        layoutParams.format = PixelFormat.RGBA_8888;
    }

    private void initListener() {
        MeetingManager.getInstance().addConfStateListener(confStateListener);
        llLeave.setOnClickListener(v -> handleLeaveConf());
        llCamera.setOnClickListener(v -> handleCameraSwith());
        llMute.setOnClickListener(v -> handleMuteClick());
        llParticipant.setOnClickListener(v -> handleParticipantsClick());
        llInvite.setOnClickListener(v -> handleInvite());
        llDialPad.setOnClickListener(v -> handleDialPadClick());
        llMore.setOnClickListener(v -> handleMoreClick());
        llShare.setOnClickListener(v -> handleShareClick());
        llSpeaker.setOnClickListener(view -> handleSpeakerClick());
    }

    /**
     * 刷新会控图标
     */
    private void updateConfCtrl() {
        CallStatus callStatus = MeetingManager.getInstance().getCallStatus();
        boolean isVideoConf = (callStatus != null && callStatus.isVideoConf());
        llParticipant.setVisibility(isVideoConf ? View.VISIBLE : View.GONE);
        llInvite.setVisibility(isVideoConf ? View.VISIBLE : View.GONE);
    }

    private void measureBottomWidth() {
        llBottomTitle.measure(measureSpecWidth, measureSpecHeight);
        int llBottomTitleWidth = llBottomTitle.getMeasuredWidth();
        LogUtil.debug(" llBottomTitleWidth in arrowClickHandle first:" + llBottomTitleWidth);
        maxPosX = ConfConst.SCREEN_WIDTH - llBottomTitleWidth - ConfConst.HORIZONTAL_MARGIN_DISTANCE;
    }

    /**
     * 获取麦克风初始状态
     */
    private void muteState() {
        isMicOpen = ConfSdkPresenter.isMicrophoneOpen();
        setMuteState();
    }

    /**
     * 获取扬声器初始状态
     */
    private void speakerState() {
        isQuite = ConfSdkPresenter.isQuiet();
        setSpeakerState();
    }

    /**
     * 获取摄像头初始状态
     */
    private void cameraState() {
        boolean cameraOpen = ConfSdkPresenter.isCameraOpen();
        isCameraOpen = cameraOpen;
        setCameraState();
    }


    /**
     * 设置麦克风状态
     */
    private void setMuteState() {
        if (isMicOpen) {
            llMuteImg.setBackground(mContext.getDrawable(R.drawable.meeting_mute_background));
        } else {
            llMuteImg.setBackground(mContext.getDrawable(R.drawable.meeting_mute_off_background));
        }
    }

    private void setSpeakerState() {
        if (isQuite) {
            llSpeakerImg.setBackground(mContext.getDrawable(R.drawable.speaker_off_background));
        } else {
            llSpeakerImg.setBackground(mContext.getDrawable(R.drawable.speaker_on_background));
        }
    }

    private void setCameraState() {
        if (isCameraOpen) {
            llCameraImg.setBackground(mContext.getDrawable(R.drawable.meeting_camera_on_background));
        } else {
            llCameraImg.setBackground(mContext.getDrawable(R.drawable.meeting_camera_off_background));
        }
    }

    /**
     * 设置音量大小
     *
     * @param state 音量值
     */
    public void setSpeakerVolume(boolean state) {
        isQuite = state;
        setSpeakerState();
    }

    /**
     * 主席 ： 显示所有会场数
     * 非主席 ： 显示会中会场数
     */
    private void refreshSiteCount() {
        LogUtil.info("refreshSiteCount()");
        List<ParticipantInfo> participantInfoList = MeetingManager.getInstance().getParticipantListInCache();
        // 如果为空主动查询一次
        if (participantInfoList == null || participantInfoList.isEmpty()) {
            participantInfoList = ConfSdkPresenter.getParticipantList();
            MeetingManager.getInstance().setParticipantList(participantInfoList);
        }
        if (participantInfoList == null || participantInfoList.isEmpty()) {
            tvSiteCount.setText(String.valueOf(0));
            return;
        }
        if (MeetingManager.getInstance().isMeChairman()) {
            String num = String.valueOf(participantInfoList.size());
            LogUtil.info("refreshSiteCount() , num : " + num);
            tvSiteCount.setText(num);
        } else {
            int inConfSiteNum = getInConfSiteNum(participantInfoList);
            LogUtil.info("refreshSiteCount() , num : " + inConfSiteNum);
            tvSiteCount.setText(String.valueOf(inConfSiteNum));
        }
    }

    private int getInConfSiteNum(List<ParticipantInfo> participantInfos) {
        int num = 0;
        for (ParticipantInfo participantInfo : participantInfos) {
            if (participantInfo.isJoinConf()) {
                num++;
            }
        }
        return num;
    }

    private void handleConfStateChangeNotify(ConfState state) {
        if (state == ConfState.CONF && isViewInit) {
            refreshControlItemStatus();
            registerListenerService();
            show();
        }
        if (state == ConfState.CONFCTRL) {
            updateConfCtrl();
            refreshSiteCount();
        }

        if (state == ConfState.NONE) {
            unRegisterListenService();
            windowManager.removeViewImmediate(view);
        }
    }

    private void handleLeaveConf() {
        leaveDialog = new LeaveDialog(mContext);
        leaveDialog.show();
    }

    /**
     * 摄像头点击设置
     */
    private void handleCameraSwith() {
        int result = -1;
        if (isCameraOpen) {
            result = ConfSdkPresenter.closeCamera();
        } else {
            result = ConfSdkPresenter.openCamera();
        }

        if (result == 0) {
            isCameraOpen = !isCameraOpen;
            setCameraState();
        } else {
            LogUtil.error("handleCameraSwith-------> Failed ");
        }
    }

    /**
     * 麦克风点击设置
     */
    private void handleMuteClick() {
        int result = -1;
        if (isMicOpen) {
            result = ConfSdkPresenter.closeMicrophone();
        } else {
            result = ConfSdkPresenter.openMicrophone();
        }

        if (result == 0) {
            isMicOpen = !isMicOpen;
            setMuteState();
        } else {
            LogUtil.error("handleMuteClick-------> Failed ");
        }
    }

    private void handleParticipantsClick() {
        LogUtil.info("handleParticipantsClick");
        if (participantsDialog != null && participantsDialog.isShow) {
            LogUtil.info("release handleParticipantsClick");
            participantsDialog.release();
            participantsDialog = null;
        } else {
            LogUtil.info("showFloatWindow handleParticipantsClick");
            if (!Settings.canDrawOverlays(mContext)) {
                RequestFloatPermissionDialog requestFloatPermissionDialog = new RequestFloatPermissionDialog(mContext);
                requestFloatPermissionDialog.show();
                return;
            }
            participantsDialog = new ParticipantsDialog(mContext, getBtnCentPosX(llParticipant), yInfo);
            participantsDialog.setAnchorView(llParticipant);
            participantsDialog.initData();
            participantsDialog.showFloatWindow();
        }
    }

    private int getBtnCentPosX(View btnView) {
        return btnView.getWidth() / 2 + (int) btnView.getX() + xInfo;
    }

    /**
     * 邀请入会
     * 1. 非主席 ，提示先申请主席
     * 2. 主席 ， 跳到邀请入会
     */
    private void handleInvite() {
        if (ConfSdkPresenter.isChairman()) {
            InviteSiteDialog inviteSiteDialog = new InviteSiteDialog(mContext, getBtnCentPosX(llInvite), yInfo);
            inviteSiteDialog.setAnchorView(llInvite);
            inviteSiteDialog.initData();
            inviteSiteDialog.showFloatWindow();
        } else {
            Toast.makeText(mContext, mContext.getResources().getString(R.string.invite_site_need_be_chairman), Toast.LENGTH_LONG).show();
        }
    }

    private void handleDialPadClick() {
        DialPadDialog dialPadDialog = new DialPadDialog(mContext);
        dialPadDialog.show();
    }

    /**
     * 点击更多
     */
    private void handleMoreClick() {
        if (!Settings.canDrawOverlays(mContext)) {
            RequestFloatPermissionDialog requestFloatPermissionDialog = new RequestFloatPermissionDialog(mContext);
            requestFloatPermissionDialog.show();
            return;
        }
        meetingSettingDialog = new MeetingSettingDialog(mContext, xInfo, yInfo);
        meetingSettingDialog.setAnchorView(llMore);
        meetingSettingDialog.showFloatWindow();
    }

    private void handleShareClick() {
        if (!ConfSdkPresenter.isSupportSendShare()) {
            Toast.makeText(mContext, "当前会议没有演示能力", Toast.LENGTH_LONG).show();
            return;
        }
        if (shareItemSelectDialog == null) {
            shareItemSelectDialog = new ShareItemSelectDialog(mContext);
        }
        shareItemSelectDialog.show();
    }

    private void handleSpeakerClick() {
        if (!Settings.canDrawOverlays(mContext)) {
            RequestFloatPermissionDialog requestFloatPermissionDialog = new RequestFloatPermissionDialog(mContext);
            requestFloatPermissionDialog.show();
            return;
        }
        if (voiceSelectWindow.isShow) {
            LogUtil.info("-------> VoiceSelectWindow release");
            voiceSelectWindow.release();
        } else {
            LogUtil.info("-------> VoiceSelectWindow show");
            voiceSelectWindow.setVolumeMenuXY(llSpeaker.getWidth() / 2 + (int) llSpeaker.getX() + 1196, yInfo);
            LogUtil.info("yInfo:" + yInfo);
            voiceSelectWindow.showFloatWindow();
        }
    }

    @Override
    public void viewDataChanged(int eventId, Object obj) {
        LogUtil.info(TAG + " viewDataChanged");
        switch (eventId) {
            case ObserverConts.MSG_ATTENDESS_CHANGE_STATUS:
                refreshSiteCount();
                break;
            default:
                break;
        }
    }

    @Override
    public void unRegisterListenService() {
        LogUtil.info(TAG + " unRegisterListenService");
        MeetingManager.getInstance().unregistDataChangeListenerObj(this);
    }

    @Override
    public void registerListenerService() {
        LogUtil.info(TAG + " registerListenerService");
        MeetingManager.getInstance().registerObserved(ObserverConts.MSG_ATTENDESS_CHANGE_STATUS, this);
    }

    public void show() {
        if (Settings.canDrawOverlays(mContext) && !view.isShown()) {
            windowManager.addView(view, layoutParams);
        } else {
            LogUtil.error(TAG + " Don't have DrawOverlay right");
        }
    }

    /**
     * 音频升视频弹框
     *
     * @param isShow true 显示
     */
    public void observeAudioToVideo(boolean isShow) {
        ConfParam confParam = ConfSdkPresenter.getConferenceParam();
        if (confParam == null) {
            LogUtil.info(TAG + " observeAudioToVideo confParam is null");
            return;
        }

        String displayName = confParam.getConferenceName() == null ? "" : confParam.getConferenceName();
        String calleeNumber = confParam.getConferenceId() == null ? "" : confParam.getConferenceId();
        String callName = displayName.length() == 0 ? calleeNumber : displayName;
        AppContext.instance().globalHandler.post(() -> showAudioToVideo(isShow, callName));
    }

    private void showAudioToVideo(boolean isShow, String callName) {
        if (!isShow) {
            CustomFloatWindow.hideFloatWindow(DialogConst.DLG_AUDIO_TO_VIDEO);
            return;
        }
        CustomFloatWindow comingCallFloatWindow = new CustomFloatWindow(mContext, DialogConst.DLG_AUDIO_TO_VIDEO, callName, mContext.getString(R.string.video_request), mContext.getString(R.string.accepting), mContext.getString(R.string.rejecting));
        // 拒绝按钮设置成红色，醒目些
        comingCallFloatWindow.setBthHighLight(FloatWindowCustomBase.HIGH_LIGHT_CAN);
        comingCallFloatWindow.setCallBack(new FloatWindowCustomBase.OnBtnClickCallBack() {
            @Override
            public void isOkBtnClick() {
                LogUtil.info(TAG + " observeAudioToVideo accept");
                // 接收
                MeetingManager.getInstance().addVideoResponse(true);
                CustomFloatWindow.hideFloatWindow(DialogConst.DLG_AUDIO_TO_VIDEO);
            }

            @Override
            public void isCancelBtnClick() {
                LogUtil.info(TAG + " observeAudioToVideo refuse");
                // 拒绝
                MeetingManager.getInstance().addVideoResponse(false);
                CustomFloatWindow.hideFloatWindow(DialogConst.DLG_AUDIO_TO_VIDEO);
            }
        });
        // 设置60秒之后自动消失
        comingCallFloatWindow.showFloatWindow(60);
    }
}
